home *** CD-ROM | disk | FTP | other *** search
- /*
- Tzong-Yow hwu
- need changes to make:
- 1. keep the number of deleted nodes of the NameTree for reconstruction
- the NameTree
- */
- #include "Scian.h"
- #include "ScianTypes.h"
- #include "ScianIDs.h"
- #include "ScianLists.h"
- #include "ScianSymbols.h"
- #include "ScianGarbageMan.h"
- #include "ScianDatabase.h"
-
- #define DB_MAXKEYS 30 /* maximum number of keys allowed in the search key list */
-
- struct LListNode
- {
- struct LListNode *next;
- Bool isVolatile; /* if it's a volatile object */
- ObjPtr object;
- };
- struct NameTreeNode
- {
- struct NameTreeNode *left;
- struct NameTreeNode *right;
- struct LListNode *list;
- char *name;
- int linkLength;
- /* the maximum number of link length of its left and right child */
- Bool deleteFlag;
- };
- typedef struct LListNode llistNode;
- typedef struct NameTreeNode nameTreeNode;
- typedef enum {FAILED = 0, SUCCESSANDNOMORE = 1, SUCCESSANDMORE = 2} Triad;
-
- /* a dummy object to be associated with the database system */
- static ObjPtr gcObject;
- static nameTreeNode *NameTree;
- static llistNode *ClassList[N_CLASS_IDS + 1];
- /* class id starting from 1
- Use 0th array element for objects whose class var is NULLOBJ */
-
- #ifdef PROTO
-
- static Triad addToNameTree(nameTreeNode **root, llistNode *listNode, char *name);
- static Bool deleteFromNameTree(ObjPtr object, char *name);
- static ObjPtr searchNameTree(char *name, int nKeys, NameTyp *keyId, ObjPtr *keyObj);
- static nameTreeNode *createNameTreeNode(llistNode *node, char *objname);
- static void freeNameTreeNode(nameTreeNode *node);
-
- static Bool addToClassArray(llistNode *node, int classid);
- static Bool deleteFromClassArray(ObjPtr object, int classid);
- static ObjPtr searchClassArray(int classid, int nKeys, NameTyp *keyId, ObjPtr *keyObj);
- static ObjPtr dumbSearch(int nKeys, NameTyp *keyId, ObjPtr *keyObj);
-
- static llistNode *createLListNode(ObjPtr object);
- static void freeLListNode(llistNode *node);
- static void addToLList(llistNode **list, llistNode *node);
- static Bool deleteFromLList(llistNode **list, ObjPtr object);
- static ObjPtr searchLList(llistNode *list, int nKeys, NameTyp *keyId, ObjPtr *keyObj);
-
- static Bool matched(ObjPtr object, int nKeys, NameTyp *keyId, ObjPtr *keyObj);
-
- #else
-
- static Triad addToNameTree();
- static Bool deleteFromNameTree();
- static ObjPtr searchNameTree();
- static nameTreeNode *createNameTreeNode();
- static void freeNameTreeNode();
-
- static Bool addToClassArray();
- static Bool deleteFromClassArray();
- static ObjPtr searchClassArray();
- static ObjPtr dumbSearch();
-
- static llistNode *createLListNode();
- static void freeLListNode();
- static void addToLList();
- static Bool deleteFromLList();
- static ObjPtr searchLList();
-
- static Bool matched();
-
- #endif
-
- /**************************** DATABASE OPERATIONS ***************************/
- #ifdef PROTO
- Bool AddToDatabase(ObjPtr object, Bool isVolatile)
- #else
- Bool AddToDatabase(object, isVolatile)
- ObjPtr object;
- Bool isVolatile;
- #endif
- {
- ObjPtr var;
- char *name;
- char *empty = "";
- int noclass = 0;
- int classid;
- llistNode *nameTreeListNode, *classArrayListNode;
-
- if (!object)
- return false;
-
- /* figure out the name of the object */
- MakeVar(object, NAME);
- var = GetVar(object, NAME);
- if (!var)
- {
- /* var is a NULLOBJ */
- name = empty;
- }
- else
- {
- name = GetString(var);
- }
-
- /* figure out the classid of the object */
- MakeVar(object, CLASSID);
- var = GetVar(object, CLASSID);
- if (!var)
- {
- classid = noclass;
- }
- else
- {
- classid = GetInt(var);
- }
-
- /* make a ClassArrayListNode and a NameTreeListNode and insert them
- into the NameTree and ClassArray respectively */
- if (!(nameTreeListNode = createLListNode(object)))
- {
- return false;
- }
- if (!(classArrayListNode = createLListNode(object)))
- {
- freeLListNode(nameTreeListNode);
- return false;
- }
-
- /* set up volatile flag */
- nameTreeListNode->isVolatile = classArrayListNode->isVolatile = isVolatile;
-
- if (FAILED == addToNameTree(&NameTree, nameTreeListNode, name) ||
- false == addToClassArray(classArrayListNode, classid))
- {
- freeLListNode(nameTreeListNode);
- freeLListNode(classArrayListNode);
- return false;
- }
- return true;
- } /* AddToDatabase */
-
- #ifdef PROTO
- Bool DeleteObjFromDatabase(ObjPtr object)
- #else
- Bool DeleteObjFromDatabase(object)
- ObjPtr object;
- #endif
- /* The deleteFlag of a Nametreenode is turned on if it has an empty
- list, i.e., the list ptr points to null */
- {
- char *name;
- char *empty = "";
- ObjPtr var;
- int classid;
- int noclass = 0;
- llistNode *treeListNode, classArrayListNode;
-
- if (!object)
- return false;
-
- MakeVar(object, NAME);
- var = GetVar(object, NAME);
- if (!var)
- {
- /* var is a NULLOBJ */
- name = empty;
- }
- else
- {
- name = GetString(var);
- }
-
- MakeVar(object, CLASSID);
- var = GetVar(object, CLASSID);
- if (!var)
- {
- classid = noclass;
- }
- else
- {
- classid = GetInt(var);
- }
-
- /* if the object is not in the name tree, it should not be in the
- class array either */
- if (!deleteFromNameTree(object, name))
- {
- if (deleteFromClassArray(object, classid))
- {
- ReportError("DeleteObjFromDatabase", "database is in inconsistent state");
- }
- /*
- Is ther a need to report an error if the object is not in the database
- else
- {
- ReportError("DeleteObjFromDatabase", "object not found");
- }
- */
- return false;
- }
- if (!deleteFromClassArray(object, classid))
- {
- ReportError("DeleteObjFromDatabase", "database is in inconsistent state");
- return false;
- }
-
- return true;
- } /* DeleteObjFromDatabase */
-
- #ifdef PROTO
- ObjPtr SearchDatabase(ObjPtr keylist)
- #else
- ObjPtr SearchDatabase(keylist)
- ObjPtr keylist;
- #endif
- /* if there is Name primarily search by NAME,
- else if there is CLASSID primarily search by CLASSID,
- else performs a linear search on the class array by the keys present */
- /* returns NULLOBJ if error, an emptylist if not found, a list otherwise */
- {
- char *emptyname = "";
- Bool isName = false; /* is name there as a key in the list */
- char *name;
-
- ObjPtr classObj;
- Bool isClassid = false; /* is class id there as a key in the list */
- int classid;
- int noclass = 0;
-
- /* construct an array of name types corresponding to keylist */
- NameTyp keyId[DB_MAXKEYS];
- /* construct an array of objptr from keylist */
- ObjPtr keyObj[DB_MAXKEYS];
-
- int index;
- int keyIndex;
- int nKeys;
- int nElements;
-
- if (!keylist)
- {
- /* keylist is a NULLOBJ */
- return dumbSearch(0, (NameTyp *) 0, (ObjPtr *) 0);
- }
- else if (!IsList(keylist) || ((nElements=ListCount(keylist)) % 2))
- {
- /* keylist must be a nonempty list and has even number of elements */
- ReportError("SearchDatabase", "Improper key list");
- return NULLOBJ;
- }
- else if (nElements == 0)
- {
- /* empty key list, return the whole database */
- return dumbSearch(0, (NameTyp *) 0, (ObjPtr *) 0);
- }
- else if ((nKeys = nElements / 2) > DB_MAXKEYS)
- {
- ReportError("SearchDatabase", "Exceeds the maximum number of allowed keys");
- return NULLOBJ;
- }
-
- keyIndex = 0;
- for (index = 0; index < nKeys; index++)
- {
- ObjPtr symbol;
- ObjPtr obj;
- NameTyp id;
-
- symbol = GetListElem(keylist, 2 * index);
- obj = GetListElem(keylist, 2 * index + 1);
- if (!IsSymbol(symbol))
- {
- ReportError("SearchDatabase", "Improper key list");
- return NULLOBJ;
- }
- id = GetSymbolID(symbol);
-
- if (id == NAME)
- {
- if (isName == true)
- {
- ReportError("SearchDatabase", "Double NAME keys in keylist");
- return NULLOBJ;
- }
- if (!obj)
- {
- name = emptyname;
- }
- else if (!IsString(obj))
- {
- ReportError("SearchDatabase", "non-string obj after NAME symbol");
- return NULLOBJ;
- }
- else
- {
- name = GetString(obj);
- }
- if (!name)
- name = emptyname;
- isName = true;
- }
- else if (id == CLASSID)
- {
- if (isClassid == true)
- {
- ReportError("SearchDatabase", "Double CLASSID keys in keylist");
- return NULLOBJ;
- }
- if (!obj)
- {
- classid = noclass;
- }
- else if (!IsInt(obj))
- {
- ReportError("SearchDatabase", "non-class obj after CLASS symbol");
- return NULLOBJ;
- }
- else
- {
- classid = GetInt(obj);
- }
- if (classid > N_CLASS_IDS || classid < 0)
- {
- ReportError("SearchDatabase", "Class id exceeds range");
- return NULLOBJ;
- }
- classObj = obj;
- isClassid = true;
- }
- else
- {
- keyId[keyIndex] = id;
- keyObj[keyIndex] = obj;
- keyIndex++;
- }
- }
- /* the search routines always return a list obj or NULLOBJ if failed */
- if (isName)
- {
- if (isClassid)
- {
- keyId[keyIndex] = CLASSID;
- keyObj[keyIndex] = classObj;
- }
- /* NAME key is not included */
- return searchNameTree(name, nKeys - 1, keyId, keyObj);
- }
- else if (isClassid)
- {
- /* CLASSID key is not included */
- return searchClassArray(classid, nKeys - 1, keyId, keyObj);
- }
- else
- {
- return dumbSearch(nKeys, keyId, keyObj);
- }
- }
-
- /* method use only old way of c function definition */
- ObjPtr MarkDatabase(gcObject)
- ObjPtr gcObject;
- {
- /* it's sufficient to mark all the objects in the Class Array */
- /* easier to traverse */
- int i;
- llistNode *runner;
-
- for (i = 0; i <= N_CLASS_IDS; i++)
- for (runner = ClassList[i]; runner; runner = runner->next)
- {
- if (runner->isVolatile == DB_NONVOLATILE)
- {
- MarkObject(runner->object);
- }
- }
- return ObjTrue;
- } /* MarkDatabase */
-
- #ifdef PROTO
- void InitDatabase(void)
- #else
- void InitDatabase()
- #endif
- {
- int i;
-
- gcObject = NewObject(NULLOBJ, 0);
- AddToReferenceList(gcObject);
- SetMethod(gcObject, MARK, MarkDatabase);
-
- /* empty database, do an initialization first */
- NameTree = (nameTreeNode *) 0;
- for (i = 0; i <= N_CLASS_IDS; i++)
- {
- ClassList[i] = (llistNode *) 0;
- }
- return;
- } /* InitDatabase */
-
- #ifdef PROTO
- void KillDatabase(void)
- #else
- void KillDatabase()
- #endif
- {
- RemoveFromReferenceList(gcObject);
- return;
- } /* KillDatabase */
-
-
- /**************************** NameTree Operations ****************************/
- /*
- This is a recursive algorithm for adding a node into a binary tree and
- maintain its balance. Balance in this case means the difference between
- any node's left and right link length is not greater than 1.
-
- When adding a linked-list node into the binary NameTree, three possible
- results may occur:
- 0. Error iff an name tree node is not able be allocated or name is a
- null pointer.
- 1. Success and the list node is inserted into the linked list of an
- already existing tree node.
- 2. Success and a new tree node is created to accomdate this list node.
-
- For case 2, a new node is created and the balance of the binary tree
- needed to be maintained. The flow of op is like this:
- When the length of the current node changed, we let the parent
- to determine whether it needs to balance its subtree by returning
- SUCCESSANDMORE value. Upon receiving the return value of
- SUCCESSANDMORE, the current node look into its rightlength and
- leftlength for determining successive actions. ? possible actions:
-
- 1. When the length of left or right child changed and their difference
- is greater than 1, we need to balance the subtree rooted at the
- current node. After a balancing op, the length of the current node
- may be different. Return accordingly.
- 2. When their difference is not greater than 1, the current node needs
- to determine whether it needs to increment its length by 1.
- If YES, return SUCCESSANDMORE.
- If NO, return SUCCESSANDNOMORE.
- */
- #ifdef PROTO
- static Triad addToNameTree(nameTreeNode **root, llistNode *listNode, char *name)
- #else
- static Triad addToNameTree(root, listNode, name)
- nameTreeNode *root;
- llistNode *listNode;
- char *name;
- #endif
- {
- int direction;
- Triad retVal;
-
- if (!name)
- return FAILED;
-
- if (!*root)
- {
- if ( !(*root = createNameTreeNode(listNode, name)) )
- return FAILED;
- return SUCCESSANDMORE;
- }
-
- direction = strcmp2((*root)->name, name);
-
- if (!direction)
- {
- if ((*root)->deleteFlag == true)
- {
- (*root)->deleteFlag = false;
- }
- addToLList(&(*root)->list, listNode);
- return SUCCESSANDNOMORE;
- }
- else if (direction < 0)
- {
- if ( SUCCESSANDMORE ==
- (retVal = addToNameTree(&((*root)->right), listNode, name)) )
- {
- /* The root's right link length is just incremented by 1, see
- if we need to do the balancing task, or changing the link length
- of the root and returns SUCCESSANDMORE */
-
- int leftLength, rightLength;
-
- /* determine the left and right length */
- leftLength = (*root)->left ? (*root)->left->linkLength : 0;
- /* there must be a right child since we just added one */
- rightLength = (*root)->right->linkLength;
-
- /* Check the length difference first and balancing accordingly */
- /* the length diff may only one of three possible values 0, 1, 2 */
- switch(rightLength - leftLength)
- {
- case 0:
- /* Before adding the node, the situation is that
- leftLength is 1 greater than rightLength,
- the link length of the root must be leftLength + 1 */
- /* balanced and no need to change link length, do nothing */
- retVal = SUCCESSANDNOMORE;
- break;
- case 1:
- /* Before adding the node, the situation is that
- rightLength is the same as leftLength */
- /* rightLength - leftLength must be 1 after adding
- the node to the right and get its rightlength
- incremented by 1. */
- (*root)->linkLength += 1;
- retVal = SUCCESSANDMORE;
- break;
- case 2:
- {
- /* Before adding the node, the situation is that
- rightLength = leftLength + 1, the link length of the
- root must be old rightLength + 1 that is the current
- value of rightlength */
- /* needs balancing */
- nameTreeNode *temp;
- int newRightLength;
-
- temp = *root;
- *root = (*root)->right;
- temp->right = (*root)->left;
- (*root)->left = temp;
-
- /* after the switching, we need calculate the linklength
- of the node currently pointed by temp, which is the
- left child of the *root now. */
- /* The result of newRightLength - leftLength is either
- 0 or 1. That's what the balancing for. */
- newRightLength = temp->right ? temp->right->linkLength : 0;
- if (newRightLength == leftLength)
- {
- temp->linkLength -= 1;
- retVal = SUCCESSANDNOMORE;
- }
- else
- {
- (*root)->linkLength += 1;
- retVal = SUCCESSANDMORE;
- }
- }
- break;
- default:
- /* dummy case */
- break;
- }
- }
- return retVal;
- }
- else
- {
- if ( SUCCESSANDMORE ==
- (retVal = addToNameTree(&((*root)->left), listNode, name)) )
- {
- int leftLength, rightLength;
-
- rightLength = (*root)->right ? (*root)->right->linkLength : 0;
- leftLength = (*root)->left->linkLength;
-
- switch(leftLength - rightLength)
- {
- case 0:
- retVal = SUCCESSANDNOMORE;
- break;
- case 1:
- (*root)->linkLength += 1;
- retVal = SUCCESSANDMORE;
- break;
- case 2:
- {
- nameTreeNode *temp;
- int newLeftLength;
-
- temp = *root;
- *root = (*root)->left;
- temp->left = (*root)->right;
- (*root)->right = temp;
-
- newLeftLength = temp->left ? temp->left->linkLength : 0;
- if (newLeftLength == rightLength)
- {
- temp->linkLength -= 1;
- retVal = SUCCESSANDNOMORE;
- }
- else
- {
- (*root)->linkLength += 1;
- retVal = SUCCESSANDMORE;
- }
- }
- break;
- default:
- /* dummy case */
- break;
- }
- }
- return retVal;
- }
- } /* addToNameTree */
-
- /* This is an iteration algorithm for pseudo deleting a node from the
- name tree. A node is pseudo deleted iff it has an empty linked list.
- Pseudo deletion is done by turning on the deleteFlag of the tree node. */
- #ifdef PROTO
- static Bool deleteFromNameTree(ObjPtr object, char *name)
- #else
- static Bool deleteFromNameTree(object, name)
- ObjPtr object;
- char *name;
- #endif
- {
- nameTreeNode *runner;
- Bool retVal;
-
- runner = NameTree;
- while(runner)
- {
- int direction;
-
- direction = strcmp2(runner->name, name);
-
- if (!direction)
- {
- if (runner->deleteFlag == true)
- {
- /*
- Is there a need to report an error when object no found.
- ReportError("deleteFromNameTree", "object not found");
- */
- return false;
- }
- retVal = deleteFromLList(&runner->list, object);
- if (!runner->list)
- {
- /* if there is no more nodes in the list, pseudo delete the node. */
- runner->deleteFlag = true;
- }
- return retVal;
- }
- else if (direction < 0)
- {
- runner = runner->right;
- }
- else
- {
- runner = runner->left;
- }
- }/* while loop */
-
- /*
- Is there a need to report an error when object no found.
- ReportError("deleteFromNameTree", "object not found");
- */
- return false;
- } /* deleteFromNameTree */
-
- #ifdef PROTO
- static ObjPtr searchNameTree(char *name, int nKeys, NameTyp *keyId, ObjPtr *keyObj)
- #else
- static ObjPtr searchNameTree(name, nKeys, keyId, keyObj)
- char *name;
- int nKeys;
- NameTyp *keyId;
- ObjPtr *keyObj;
- #endif
- {
- nameTreeNode *runner;
-
- runner = NameTree;
- while(runner)
- {
- int direction;
-
- direction = strcmp2(runner->name, name);
-
- if (!direction)
- {
- if (runner->deleteFlag == false)
- {
- return searchLList(runner->list, nKeys, keyId, keyObj);
- }
- else
- {
- return NewList();
- }
- }
- else if (direction < 0)
- {
- runner = runner->right;
- }
- else
- {
- runner = runner->left;
- }
- }/* while loop */
-
- return NewList();
- } /* searchNameTree */
-
- #ifdef PROTO
- static nameTreeNode *createNameTreeNode(llistNode *node, char *objname)
- #else
- static nameTreeNode *createNameTreeNode(node, objname)
- llistNode *node;
- char *objname;
- #endif
- /* Construct a new tree node and add node at the beginning of the tree node list */
- {
- nameTreeNode *retVal;
-
- if (!(retVal = (nameTreeNode *) Alloc(sizeof(nameTreeNode))))
- {
- ReportError("createNameTreeNode", "out of memory");
- return (nameTreeNode *) 0;
- }
-
- if (!(retVal->name = (char *) Alloc((strlen(objname) + 1) * sizeof(char))))
- {
- Free(retVal);
- ReportError("createNameTreeNode", "out of memory");
- return (nameTreeNode *) 0;
- }
-
- strcpy(retVal->name, objname);
- retVal->left = (nameTreeNode *) 0;
- retVal->right = (nameTreeNode *) 0;
- retVal->list = node;
- retVal->deleteFlag = false;
- retVal->linkLength = 1; /* a newly created tree node is going to be
- at the leaf position which is of link length
- 1 */
-
- return retVal;
- } /* createNameTreeNode */
-
- #ifdef PROTO
- static void freeNameTreeNode(nameTreeNode *node)
- #else
- static void freeNameTreeNode(node)
- nameTreeNode *node;
- #endif
- {
- Free(node->name);
- Free(node);
- return;
- }
-
-
- /**************************** ClassArray Operations ****************************/
- #ifdef PROTO
- static Bool addToClassArray(llistNode *node, int classid)
- #else
- static Bool addToClassArray(node, classid)
- llistNode *node;
- int classid;
- #endif
- {
- if (classid < 0 || classid > N_CLASS_IDS)
- {
- ReportError("addToClassArray", "Class id exceeds range");
- return false;
- }
- else
- {
- addToLList(ClassList + classid, node);
- return true;
- }
- } /* addToClassArray */
-
- #ifdef PROTO
- static Bool deleteFromClassArray(ObjPtr object, int classid)
- #else
- static Bool deleteFromClassArray(object, classid)
- ObjPtr object;
- int classid;
- #endif
- {
- if (classid < 0 || classid > N_CLASS_IDS)
- {
- ReportError("deleteFromClassArray", "Class id exceeds range");
- return false;
- }
- else
- {
- return deleteFromLList(ClassList + classid, object);
- }
- } /* deleteFromClassArray */
-
- #ifdef PROTO
- static ObjPtr searchClassArray(int classid, int nKeys, NameTyp *keyId, ObjPtr *keyObj)
- #else
- static ObjPtr searchClassArray(classid, nKeys, keyId, keyObj)
- int classid;
- int nKeys;
- NameTyp *keyId;
- ObjPtr *keyObj;
- #endif
- {
- if (classid < 0 || classid > N_CLASS_IDS)
- {
- ReportError("searchClassArray", "Class id exceeds range");
- return NULLOBJ;
- }
- else
- {
- return searchLList(ClassList[classid], nKeys, keyId, keyObj);
- }
- }
-
- #ifdef PROTO
- static ObjPtr dumbSearch(int nKeys, NameTyp *keyId, ObjPtr *keyObj)
- #else
- static ObjPtr dumbSearch(nKeys, keyId, keyObj)
- int nKeys;
- NameTyp *keyId;
- ObjPtr *keyObj;
- #endif
- {
- int runner;
- ObjPtr newlist;
- ObjPtr retVal = NULLOBJ;
-
- for (runner = 0; runner <= N_CLASS_IDS; runner++)
- {
- newlist = searchLList(ClassList[runner], nKeys, keyId, keyObj);
- if (!newlist)
- {
- return NULLOBJ;
- }
- else
- {
- if (ListCount(newlist) > 0)
- {
- if (!retVal)
- {
- if (!(retVal = NewList()))
- {
- ReportError("dumbSearch", "Unable to get a new list");
- return NULLOBJ;
- }
- }
- AppendList(retVal, newlist);
- }
- }
- }
- return retVal;
- }
-
- /****************************** LList Operations *******************************/
-
- #ifdef PROTO
- static llistNode *createLListNode(ObjPtr object)
- #else
- static llistNode *createLListNode(object)
- ObjPtr object;
- #endif
- {
- llistNode *retVal;
-
- if (!(retVal = (llistNode *) Alloc(sizeof(llistNode))))
- {
- ReportError("createLListNode", "out of memory");
- return (llistNode *) 0;
- }
- else
- {
- retVal->object = object;
- retVal->next = (llistNode *) 0;
- return retVal;
- }
- } /* createLListNode */
-
- #ifdef PROTO
- static void freeLListNode(llistNode *node)
- #else
- static void freeLListNode(node)
- llistNode *node;
- #endif
- {
- Free(node);
- return;
- } /* freeLListNode */
-
- #ifdef PROTO
- static void addToLList(llistNode **list, llistNode *node)
- #else
- static void addToLList(list, node)
- llistNode **list;
- llistNode *node;
- #endif
- {
- node->next = *list;
- *list = node;
-
- return;
- }
-
- #ifdef PROTO
- static Bool deleteFromLList(llistNode **list, ObjPtr object)
- #else
- static Bool deleteFromLList(list, object)
- llistNode **list;
- ObjPtr object;
- #endif
- {
- llistNode *current, *previous;
-
- current = *list;
-
- while(current)
- {
- if (current->object == object)
- /* object found */
- {
- /* at the beggining of the list */
- if (current == *list)
- {
- *list = current->next;
- }
- /* somewhere after first node in the list */
- else
- {
- previous->next = current->next;
- }
- freeLListNode(current);
- return true;
- }
- else
- {
- previous = current;
- current = current->next;
- }
- }
-
- /*
- Is there a need to report that the object is not found within the list.
-
- ReportError("deleteFromLList", "object not found");
- */
- return false;
- }
-
- #ifdef PROTO
- static ObjPtr searchLList(llistNode *list, int nKeys, NameTyp *keyId, ObjPtr *keyObj)
- #else
- static ObjPtr searchLList(list, nKeys, keyId, keyObj)
- llistNode *list;
- int nKeys;
- NameTyp *keyId;
- ObjPtr *keyObj;
- #endif
- {
- llistNode *runner;
- ObjPtr retVal;
-
- if (!(retVal = NewList()))
- {
- ReportError("searchLList", "Unable to get a new list");
- return NULLOBJ;
- }
-
- runner = list;
- while(runner)
- {
- if (true == matched(runner->object, nKeys, keyId, keyObj))
- {
- if (!PrefixList(retVal, runner->object))
- {
- ReportError("searchLList", "Unable to Prefix to list");
- return NULLOBJ;
- }
- }
- runner = runner->next;
- }
-
- return retVal;
- }
-
- /************************** matching operation ******************************/
-
- #ifdef PROTO
- static Bool matched(ObjPtr object, int nKeys, NameTyp *keyId, ObjPtr *keyObj)
- #else
- static Bool matched(object, nKeys, keyId, keyObj)
- ObjPtr object;
- int nKeys;
- NameTyp *keyId;
- ObjPtr *keyObj;
- #endif
- {
- Bool matched = true;
- int i;
-
- for (i = 0; matched && i < nKeys; i++)
- {
- ObjPtr varObj;
-
- MakeVar(object, keyId[i]);
- varObj = GetVar(object, keyId[i]);
-
- if (IsString(keyObj[i]))
- {
- if (!IsString(varObj))
- {
- return false;
- }
- else
- {
- char *keyString, *varString;
-
- keyString = GetString(keyObj[i]);
- varString = GetString(varObj);
- matched = strcmp2(keyString, varString) ? false : true;
- }
- }
- else
- {
- matched = Equal(varObj, keyObj[i]);
- }
- }
-
- return matched;
- }
-
- #ifdef PROTO
- ObjPtr NewUniqueName(char *oldName, int classID)
- #else
- ObjPtr NewUniqueName(oldName, classID)
- char *oldName;
- int classID;
- #endif
- /*Generates a new name based on oldName which does not conflict with existing
- objects of classID in the database*/
- {
- char trialName[400];
- char *s;
- int k;
-
- if (!DatabaseConflict(oldName, classID))
- {
- return NewString(oldName);
- }
-
- strcpy(trialName, oldName);
-
- s = trialName;
- while (*s) ++s;
- while (s > trialName && isspace(*s)) *s-- = 0;
- --s;
- if (s > trialName && isdigit(*s)) --s;
- {
- while (s > trialName && isdigit(*s)) --s;
- if (s > trialName && *s == '#')
- {
- --s;
- while (s > trialName && isspace(*s)) --s;
- if (s >= trialName)
- {
- ++s;
- *s = 0;
- }
- }
- }
- while (*s) ++s;
-
- for (k = 2; ; ++k)
- {
- sprintf(s, " #%d", k);
- if (!DatabaseConflict(trialName, classID))
- {
- return NewString(trialName);
- }
- }
- }
-